
#ifndef _BOARD_H_
#define _BOARD_H_

typedef struct _Cell
{
	int row;
	int col;

	bool IsSame(const struct _Cell &c)
	{
		return (row == c.row && col == c.col);
	}

	struct _Cell Left()
	{
		struct _Cell left = {row, col-1};
		return left;
	}

	struct _Cell Right()
	{
		struct _Cell right = {row, col+1};
		return right;
	}

	struct _Cell Up()
	{
		struct _Cell up = {row-1, col};
		return up;
	}

	struct _Cell Down()
	{
		struct _Cell down = {row+1, col};
		return down;
	}
} Cell;

class Board
{
private:
	int m_nSize;
	int *m_pValues;
	int *m_pMerged;
	int m_nScore;
	Cell *m_pAvailableCells;

public:
	Board(int size = 4);
	Board(const Board &b);
	~Board(void);

	Board & operator=(const Board &b);
	inline int & Value(const int &r, const int &c) { return m_pValues[r * m_nSize + c]; }
	inline int & Value(const Cell &c) { return m_pValues[c.row * m_nSize + c.col]; }

	const bool MoveLeft();
	const bool MoveRight();
	const bool MoveUp();
	const bool MoveDown();
	const bool CanMove();
	const int AvailableCellsCount();
	const Cell* AvailableCells();
	
	inline int IsValidCell(const Cell &c) { return !(c.row < 0 || c.row >= m_nSize || c.col < 0 || c.col >= m_nSize); }
	inline const int & Size() { return m_nSize; }
	inline const int & Score() { return m_nScore; }

	void Print();
	void Print(const Cell &recent);
	const float Evaluate();

private:
	inline int & Merged(const Cell &c) { return m_pMerged[c.row * m_nSize + c.col]; }
	void ResetMerged();
	const int Monocity2();
	const int MaxValue();
};

#endif

